﻿<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta http-equiv="pragma" content="no-cache" />
    <meta http-equiv="Cache-Control" content="no-cache, must-revalidate" />
    <meta http-equiv="expires" content="0" />
    <title>FaceCat-Html5</title>
</head>
<body>
    <canvas id="pyCanvas" width="400" height="700" style="position: fixed; left: 0px; top: 0px;" />
    <script type="text/javascript" src="facecat.js"></script>
    <script type="text/javascript">
        let canvasPy = document.getElementById("pyCanvas"); //绘图区域
        canvasPy.width = window.innerWidth;
        canvasPy.height = window.innerHeight;
        let gPaint = new FCPaint(); //绘图对象
        gPaint.canvas = canvasPy;
        scaleCanvas(gPaint);
        
        gPaint.defaultUIStyle = "dark";
        //判断是否移动端
        gPaint.isMobile = isMobileMode();
        if (gPaint.isMobile) {
            gPaint.scaleFactorX = 2.5;
            gPaint.scaleFactorY = 2.5;
        }
        addDefaultEvent(canvasPy, gPaint);
        //面积图数据
        class PyrometerData {
            constructor() {
                this.text = ""; //数值
                this.key = ""; //键
                this.lastClose = 0; //开始数据
                this.close = 0; //最新数据
                this.value = 0; //数值
                this.location = new FCPoint(0, 0); //位置
                this.size = new FCSize(0, 0); //大小
            }
        }

        /*
        * 面积图
        */
        class PyrometerDiv extends FCView {
            constructor() {
                super();
                this.useAnimation = false; //是否使用动画
                super.viewType = "pyrometer"; //类型
                this.INF = 0x3f3f3f; //无效数据
                this.Rwidth = 0 //横向宽度
                this.Rheight = 0; //纵向宽度
                this.rects = new Array(); //显示区域
                this.children = new Array();
            }
        }

        //创建买卖档
        let pyrometer = new PyrometerDiv();
        pyrometer.dock = "fill";
        //添加到框架
        addView(pyrometer, gPaint);
        //根据主题色配色
        if (pyrometer.paint.defaultUIStyle == "dark") {
            pyrometer.backColor = "rgb(0,0,0)";
            pyrometer.borderColor = "rgb(100,100,100)";
            pyrometer.textColor = "rgb(255,255,255)";
        } else if (pyrometer.paint.defaultUIStyle == "light") {
            pyrometer.backColor = "rgb(255,255,255)";
            pyrometer.borderColor = "rgb(150,150,150)";
            pyrometer.textColor = "rgb(0,0,0)";
        }
        //计算大小
        let layoutrow = function (pyrometer, R, w) {
            let width = pyrometer.size.cx;
            let height = pyrometer.size.cy;
            let lx = width - pyrometer.Rwidth;
            let ly = height - pyrometer.Rheight;
            let direction = 0;  

            let sum = 0;
            for (let x = 0; x < R.length; x++) {
                sum += R[x];
            }
            let ext = sum / w;
            if (Math.abs(w - pyrometer.Rwidth) <= 1e-6) {
                pyrometer.Rheight -= ext;
                direction = 0;
            }
            else {
                pyrometer.Rwidth -= ext;
                direction = 1;
            }

            for (let x = 0; x < R.length; x++) {
                let r = R[x];
                if (direction == 0) {
                    let hh = ext, ww = r / ext;
                    let newRect = new FCRect(0, 0, 0, 0);
                    newRect.left = Math.floor(lx);
                    newRect.top = Math.floor(ly);
                    newRect.right = Math.ceil(lx + ww);
                    newRect.bottom = Math.ceil(ly + hh);
                    pyrometer.rects.push(newRect);
                    lx += ww;
                }
                else {
                    let ww = ext, hh = r / ext;
                    let newRect = new FCRect(0, 0, 0, 0);
                    newRect.left = Math.floor(lx);
                    newRect.top = Math.floor(ly);
                    newRect.right = Math.ceil(lx + ww);
                    newRect.bottom = Math.ceil(ly + hh);
                    pyrometer.rects.push(newRect);
                    ly += hh;
                }
            }
        };

        //计算横向宽度
        let rWidth = function (pyrometer, R, w) {
            return Math.min(pyrometer.Rwidth, pyrometer.Rheight);
        };

        //计算最差结果
        let worst = function (pyrometer, R, w) {
            if (R.length == 0) {
                return pyrometer.INF;
            }
            let rmx = 0, rmn = pyrometer.INF, s = 0;
            for (let x = 0; x < R.length; x++) {
                let r = R[x];
                s += r;
                if (r > rmx) rmx = r;
                if (r < rmn) rmn = r;
            }
            let pw = Math.pow(w, 2), sw = Math.pow(s, 2);
            let res = Math.max(pw * rmx / sw, sw / (pw * rmn));
            return Math.max(pw * rmx / sw, sw / (pw * rmn));
        };

        /*
        * 动画秒表
        */
        let onPyrometerTime = function (pyrometer) {
            let paint2 = false;
            if (pyrometer.useAnimation) {
                for (let i = 0; i < pyrometer.rects.length; i++) {
                    let subView = pyrometer.children[i];
                    let targetRect = pyrometer.rects[i];
                    let nowRect = new FCRect(subView.location.x, subView.location.y, subView.location.x + subView.size.cx, subView.location.y + subView.size.cy);
                    if (true) {
                        if (nowRect.left > targetRect.left) {
                            nowRect.left -= (nowRect.left - targetRect.left) / 4;
                            if (nowRect.left - targetRect.left < 10) {
                                nowRect.left = targetRect.left;
                            }
                            paint2 = true;
                        }
                        else if (nowRect.left < targetRect.left) {
                            nowRect.left += (targetRect.left - nowRect.left) / 4;
                            if (targetRect.left - nowRect.left < 10) {
                                nowRect.left = targetRect.left;
                            }
                            paint2 = true;
                        }
                    }

                    if (true) {
                        if (nowRect.top > targetRect.top) {
                            nowRect.top -= (nowRect.top - targetRect.top) / 4;
                            if (nowRect.top - targetRect.top < 10) {
                                nowRect.top = targetRect.top;
                            }
                            paint2 = true;
                        }
                        else if (nowRect.top < targetRect.top) {
                            nowRect.top += (targetRect.top - nowRect.top) / 4;
                            if (targetRect.top - nowRect.top < 10) {
                                nowRect.top = targetRect.top;
                            }
                            paint2 = true;
                        }
                    }

                    if (true) {
                        if (nowRect.right > targetRect.right) {
                            nowRect.right -= (nowRect.right - targetRect.right) / 4;
                            if (nowRect.right - targetRect.right < 10) {
                                nowRect.right = targetRect.right;
                            }
                            paint2 = true;
                        }
                        else if (nowRect.right < targetRect.right) {
                            nowRect.right += (targetRect.right - nowRect.right) / 4;
                            if (targetRect.right - nowRect.right < 10) {
                                nowRect.right = targetRect.right;
                            }
                            paint2 = true;
                        }
                    }
                    if (true) {
                        if (nowRect.bottom > targetRect.bottom) {
                            nowRect.bottom -= (nowRect.bottom - targetRect.bottom) / 4;
                            if (nowRect.bottom - targetRect.bottom < 10) {
                                nowRect.bottom = targetRect.bottom;
                            }
                            paint2 = true;
                        }
                        else if (nowRect.bottom < targetRect.bottom) {
                            nowRect.bottom += (targetRect.bottom - nowRect.bottom) / 4;
                            if (targetRect.bottom - nowRect.bottom < 10) {
                                nowRect.bottom = targetRect.bottom;
                            }
                            paint2 = true;
                        }
                    }
                    subView.location = new FCPoint(nowRect.left, nowRect.top);
                    subView.size = new FCSize(nowRect.right - nowRect.left, nowRect.bottom - nowRect.top);
                }
            } else {
                for (let i = 0; i < pyrometer.rects.length; i++) {
                    let subView = pyrometer.children[i];
                    let targetRect = pyrometer.rects[i];
                    subView.location = new FCPoint(targetRect.left, targetRect.top);
                    subView.size = new FCSize(targetRect.right - targetRect.left, targetRect.bottom - targetRect.top);
                }
            }
            if (paint2) {
                invalidateView(pyrometer);
            }
        };

        /*
        * 更新数据
        */
        let updatePyromoter = function (pyrometer) {
            pyrometer.rects = new Array();
            let totalAmount = 0;
            for (let i = 0; i < pyrometer.children.length; i++) {
                totalAmount += pyrometer.children[i].value;
            }
            let rates = new Array();
            for (let i = 0; i < pyrometer.children.length; i++) {
                rates.push(pyrometer.children[i].value / totalAmount);
            }
            pyrometer.Rwidth = pyrometer.size.cx;
            pyrometer.Rheight = pyrometer.size.cy;
            let areas = new Array();
            for (let i = 0; i < rates.length; i++) {
                areas.push(rates[i] * pyrometer.size.cx * pyrometer.size.cy);
            }
            let children = areas;
            let row = new Array();
            let w = Math.min(pyrometer.Rwidth, pyrometer.Rheight);
            while (true) {
                if (pyrometer.rects.length > pyrometer.children.length) {
                    break;
                }
                if (w <= 0) {
                    break;
                }
                if (children.length == 0) {
                    if (row.length > 0) {
                        layoutrow(pyrometer, row, w);  
                    }
                    break;
                }

                let c = children[0];
                if(c == 0){
                    layoutrow(pyrometer, row, w); 
                    break;
                }
                let newrow = new Array();
                for (let x = 0; x < row.length; x++) {
                    newrow.push(row[x]);
                }
                newrow.push(c);
                if (worst(pyrometer, row, w) >= worst(pyrometer, newrow, w)) { 
                    let tmp = new Array();
                    for (let x = 1; x < children.length; x++) {
                        tmp.push(children[x]);
                    }
                    children = tmp;
                    row = newrow;
                }
                else {  
                    layoutrow(pyrometer, row, w);  
                    row = new Array();
                    w = rWidth(pyrometer, row, parseInt(w));
                }
            }
        };

        /*
        * 重绘背景的实现方法
        * view:视图
        * paint:绘图对象
        * clipRect:裁剪区域
        */
        gPaint.onPaint = function (view, paint, clipRect) {
            if (view.viewType == "pyrometer") {
                drawDiv(view, paint, clipRect);
                for (let i = 0; i < view.children.length; i++){
                    let pData = view.children[i];
                    let backColor = "none";
                    let borderColor = "none";
                    if (paint.defaultUIStyle == "dark"){
                        if (pData.close >= pData.lastClose){
                            backColor = "rgb(219,68,83)";
                        }
                        else{
                            backColor = "rgb(15,193,118)";
                        }
                        borderColor = "rgb(0,0,0)";
                    }
                    else if (paint.defaultUIStyle == "light"){
                        if (pData.close >= pData.lastClose){
                            backColor = "rgb(255,255,255)";
                        }
                        else{
                            backColor = "rgb(255,255,255)";
                        }
                        borderColor = "rgb(255,255,255)";
                    }
                    paint.fillRect(backColor, pData.location.x, pData.location.y, pData.location.x + pData.size.cx, pData.location.y + pData.size.cy);
                    paint.drawRect(borderColor, 1, 0, pData.location.x, pData.location.y, pData.location.x + pData.size.cx, pData.location.y + pData.size.cy);
                    let fontSize1 = (Math.min(pData.size.cx, pData.size.cy) / 5);
                    if (fontSize1 > 1){
                        let baseUpper = pData.text;
                        let font1 = "Default," + fontSize1.toString();
                        let tSize = paint.textSize(baseUpper, font1);
                        let isContinue = false;
                        while (tSize.cx > pData.size.cx - 10){
                            fontSize1 = fontSize1 - 1;
                            if (fontSize1 < 2){
                                isContinue = true;
                                break;
                            }
                            font1 = "Default," + fontSize1.toString();
                            tSize = paint.textSize(baseUpper, font1);
                        }
                        if (isContinue){
                            continue;
                        }
                        let quoteUpper = pData.key;
                        let font2 = "Default," + (fontSize1 / 2).toString();
                        let tSize2 = paint.textSize(quoteUpper, font2);
                        if (paint.defaultUIStyle == "dark"){
                            paint.drawText(baseUpper, "rgb(255,255,255)", font1, pData.location.x + (pData.size.cx - tSize.cx) / 2, pData.location.y + pData.size.cy / 2 - tSize.cy - tSize.cy / 2);
                            paint.drawText(quoteUpper, "rgb(255,255,255)", font2, pData.location.x + (pData.size.cx - tSize2.cx) / 2, pData.location.y + pData.size.cy / 2 - tSize.cy / 4);
                        }
                        else if (paint.defaultUIStyle == "light"){
                            paint.drawText(baseUpper, "rgb(0,0,0)", font1, pData.location.x + (pData.size.cx - tSize.cx) / 2, pData.location.y + pData.size.cy / 2 - tSize.cy - tSize.cy / 2);
                            paint.drawText(quoteUpper, "rgb(0,0,0)", font2, pData.location.x + (pData.size.cx - tSize2.cx) / 2, pData.location.y + pData.size.cy / 2 - tSize.cy / 4);
                        }
                        let strPrice = "0.00%";
                        if(pData.lastClose > 0){
                            strPrice = (100 * (pData.close - pData.lastClose) / pData.lastClose).toFixed(2) + "%"
                            if(pData.close > pData.lastClose){
                                strPrice = "+" + strPrice;
                            }
                        }
                        let font3 = "Default," + (fontSize1 * 2 / 3).toString();
                        let tSize5 = paint.textSize(strPrice, font3);
                        if (paint.defaultUIStyle == "dark"){
                            paint.drawText(strPrice, "rgb(255,255,255)", font3, pData.location.x + (pData.size.cx - tSize5.cx) / 2, pData.location.y + pData.size.cy / 2 + tSize.cy - tSize.cy / 2);
                        }else if (paint.defaultUIStyle == "light"){
                            paint.drawText(strPrice, "rgb(0,0,0)", font3, pData.location.x + (pData.size.cx - tSize5.cx) / 2, pData.location.y + pData.size.cy / 2 + tSize.cy - tSize.cy / 2);
                        }
                    }
                }
            } else{
                onPaintDefault(view, paint, clipRect);
            }
        };

        /*
        * 更新布局状态
        * views:视图集合
        */
        let updateView = function(views){
            updateViewDefault(views);
            for (let i = 0; i < views.length; i++) {
                let view = views[i];
                if (view.viewType == "pyrometer"){
                    updatePyromoter(view);
                    onPyrometerTime(view);
                }
            }
        };

        gPaint.onUpdateView = updateView;

        /*
        * 重置所有的大小
        */
        let resizeAll = function () {
            canvasPy.width = document.documentElement.clientWidth;
            canvasPy.height = document.documentElement.clientHeight;
            scaleCanvas(gPaint);
            updateView(gPaint.views);
            invalidate(gPaint);
        };

        /*
        * 重置大小
        */
        window.onresize = function () {
            resizeAll();
        };

        /*
        * 旋转监听
        */
        window.onorientationchange = function () {
            resizeAll();
        };

        let pDatas = new Map();

        let queryPrice = function(){
            let url = "http://110.42.188.197:9968/quote?func=price&count=100&codes=all";
            let xmlhttp = new XMLHttpRequest();
            xmlhttp.open("GET", url, true);
            xmlhttp.onreadystatechange = function () {
                if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
                    let result = xmlhttp.responseText;
                    let strs = result.split("\r\n");
                    let pos = 0;
                    for(let i = 1; i < strs.length; i++){
                        let subStrs = strs[i].split(",");
                        if(subStrs.length >= 15){
                            let pData = 0;
                            let key = subStrs[0];
                            if(pDatas.has(key)){
                                pData = pDatas.get(key);
                            }else{
                                pData = new PyrometerData;
                                pDatas.set(key, pData);
                                pData.size = new FCSize(0, 0);
                                pData.location = new FCPoint(pyrometer.size.cx, pyrometer.size.cy);
                                pyrometer.children.push(pData);
                            }
                            pData.key = key;
                            pData.text = subStrs[1];
                            pData.value = parseFloat(subStrs[6]);
                            pData.lastClose = parseFloat(subStrs[8]);
                            pData.close = parseFloat(subStrs[2]); 
                            pos++;
                        }
                    }
                    pyrometer.children.sort((m, n) => {
                        if (m.value > n.value) {
                            return -1;
                        }
                        else if (m.value < n.value) {
                            return 1;
                        }
                        else return 0;
                    });
                    updateView(gPaint.views);
                    invalidateView(pyrometer);
                }
            }
            xmlhttp.send(null);
        };
        
        queryPrice();
        //setInterval(queryPrice, 1000);
    </script>
</body>
</html>
